/*  
     PlAr is Platform Arena: a 2D multiplayer shooting game
     Copyright (C) 2009 Ragagnin Antonio <spocchio@gmail.com>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package plar.core;

import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;


import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.ContactListener;
import org.jbox2d.dynamics.DestructionListener;
import org.jbox2d.dynamics.World; 

import org.jbox2d.common.*;

import org.jbox2d.dynamics.contacts.ContactPoint;
import org.jbox2d.dynamics.contacts.ContactResult;
import org.jbox2d.dynamics.joints.Joint;
import org.jbox2d.collision.*;
public class Level implements Runnable {

	public Parameters info;
	public World world;
	public int iterations=1;
	public float dt=0.015f;
	public Vec2 dim;
	public Vec2 g;
	public Level(Vec2 s,Vec2 f) {
		dim=s;
		g=f;
	}


	public void Initialize()
	{
		/*world.setDestructionListener(new DestructionListener (){
		
		public void sayGoodbye(Joint joint) {
			Common.info(7,"we all miss that joint: "+joint);	
			
		}
		
		public void sayGoodbye(Shape shape) {
			Common.info(7,"we all miss that sheik: "+shape);
			
				}
			}
		);
		*/
		 world.setContactListener(new ContactListener(){

			
			public void add(ContactPoint point) {
				if(point.separation<0)
				{

				
				//Common.info("collision at:"+point.position);
				Element e1 = (Element)point.shape1.getBody().getUserData();
				Element e2 = (Element)point.shape2.getBody().getUserData();
				
				setCollision(e1,e2);
				setCollision(e2,e1);
				Common.info(4,"Collision detected: beetween "+e1+" & "+e2 );
				
				}
			}
			
			
		
			private void setCollision(Element e1, Element e2) {
				if((Boolean)(e1.getProperty("isRunnable")))
						{
				ArrayList <Element> cl1 = (ArrayList <Element>)e1.getProperty("collisionList");
				
				if(cl1==null) cl1= new ArrayList <Element>();
				if(!cl1.contains(e2))	cl1.add(e2);
				e1.setProperty("collisionList",cl1);
						}
				
			}

			
			
			public void persist(ContactPoint point) {
				//add(point);
				
			}

			
			
			
			public void remove(ContactPoint point) {
				
			}

		
				
			public void result(ContactResult point) {
				
			}
     });
		

	}
	public void AddElement(Element e)
	{
		//boolean ac = (Boolean)e.getProperty("isActive");
		//e.bd.active=ac;
		float ld = (Float)e.getProperty("linearDamping");
		e.bd.linearDamping=ld;
		e.body =  world.createBody(e.bd);
		
		if(e.body==null)
		{
			Common.info(1,"Level: new Body is null: "+e);
		}else{
		//Common.info(8,"e.bd:"+e.bd);
		//Common.info(8,"e.body:"+e.body);
		//Common.info("body type:"+e.body.m_type);
		e.JBoxSincronize();
		//Common.info(8,"body type:"+e.body.m_type);
		e.body.setUserData(e);
		e.level = this;
   // Common.info(7,"Level.addElement() "+e.pd.friction);
		}
			
	}
	
	public void delElement(Element e) {
		
		Common.info(3,"Level.delElement(): deleting "+e.body.getUserData());
		world.destroyBody(e.body);
	}



	public ArrayList<Element> getElementsByType(String s) {
			return getElementsByProperty("type",s);
	}
	public ArrayList<Element> getElementsByProperty(String k,Object v) {
		ArrayList<Element> l = new ArrayList<Element>();
		Body b=world.getBodyList();
		
		while(b!=null)
		{
			Element e = (Element)b.getUserData();
			if(e!=null)
			{
				if(e.getProperty(k)!=null)
					if (e.getProperty(k).equals(v))
						l.add(e);
			}
			//else Common.info("oh my gosh:"+k+", "+v+", "+b+", "+e);
			b = b.getNext();
		}

		return l;
	}

	public ArrayList<Element> getPlayers() {
		return getElementsByType("player");

	}

public ArrayList<Element> getGravities() {
	return getElementsByProperty("hasGravity",true);
	}

	public ArrayList<Element> getRunnable() {
		return getElementsByProperty("isRunnable",true);

	}

	public ArrayList<Element> getScreen(Vec2 a,Vec2 b) {
		AABB r=new AABB();
		r.lowerBound=new Vec2(a.x,a.y);
		r.upperBound=new Vec2(a.x+b.x,a.y+b.y);
		ArrayList<Element> al=new ArrayList<Element> ();
			try{
		Shape [] ss = world.query(r, 1500);
	
		
		for(Shape s:ss)
			{
			al.add((Element)s.getBody().getUserData());
		}
	}catch(Exception ex)
	{
		Common.info(1,"Level.getScreen() got exception:"+ex);
	}
		return al;
	}

	public void run() {
		

		//for(int i=0;i<1000;i++)
		//Common.info(1,"runn()");
		try
		{
	    	world.step(dt,iterations);
		}
		catch(Exception ex)
		{
			Common.info(1,"JBox2D FAIL"+ex);
		}
        for (Element e : getRunnable()) {
			e.run();
		}

	

	}

}
